#include "TesselCube.h"


#include <gl/glfw.h>

#include <math.h>
#include "color_utils.h"


// side = front,back,left,right,top,bottom
Vec3f TesselCube::cube(int side,float s, float t){
	Vec3f point;
	if(side==0){
		point.is(1-2*s,1-2*t,1);
	}else if(side==1){
		point.is(1-2*s,1-2*t,-1);
	}else if(side==2){
		point.is(-1,1-2*s,1-2*t);
	}else if(side==3){
		point.is(1,1-2*s,1-2*t);
	}else if(side==4){
		point.is(1-2*s,1,1-2*t);
	}else if(side==5){
		point.is(1-2*s,-1,1-2*t);
	}
	return point;
}

	float lerp( float x1, float x2, float t)
	{
		return x1 + (x2-x1)*t;
	}


	void TesselCube::init()
		{
			faceMorphPositions.resize(6*dim1*dim2, 1.0f);

			vertices.resize(6);
			colors.resize(6);
			normals.resize(6);
			for(size_t i=0; i<6; i++)
			{
				vertices[i].resize(dim1);
				colors[i].resize(dim1);
				normals[i].resize(dim1);
				for(size_t j=0; j<dim1; j++)
				{
					vertices[i][j].resize(dim2);
					colors[i][j].resize(dim2);
					normals[i][j].resize(dim2);
				}
			}

			int faceIdx = 0;
			for(int side=0; side<6; side++)
			{
				for(int i=0; i<dim1; i++)
				{
					for(int j=0; j<dim2; j++)
					{
						float s = float(i)/(dim1-1);
						float t = float(j)/(dim2-1);
						//float sdt = s + 0.01f;
						//float tdt = t + 0.01f;

						Vec3f &pointOnCube = cube(side,t,s);
						//Vec3f &pointOnCubeS = cube(side,sdt,t);
						//Vec3f &pointOnCubeT = cube(side,s,tdt);

						Vec3f norm = normalize( pointOnCube );

						//  Vec3f( r,g,b );
						//float r=0; float g=0; float b=0;
						//TorColor::hsv_to_rgb( faceIdx / float(getFaceCount()) * 360.0f, 1.0f, 1.0f, r, g, b);

						colors[side][i][j] = 0.5f + norm * 0.5f;
						vertices[side][i][j] = norm;
						normals[side][i][j] = norm;

						faceIdx++;
					} // for j
				} // for i 
			} // for s 
		}

	
	void TesselCube::morph()
	{
		glDisable(GL_CULL_FACE);
		glCullFace(GL_NONE);
		glEnable(GL_COLOR_MATERIAL);
		glDepthFunc(GL_LEQUAL);
		//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
		//glDisable(GL_LIGHTING);

		// Extended quad vertices
		Vec3f extBL;
		Vec3f extBR;
		Vec3f extTR;
		Vec3f extTL;
		// Indices for convenience:
		int u = 0;
		int v = 0;

		int faceIdx=0;
		for(size_t s=0; s<6; s++)
		{
			for(size_t i=0; i<dim1-1; i++)
			{
				glBegin(GL_QUADS);
				for(size_t j=0; j<dim2-1; j++)  
				{      
					if(0)
					{
						u=i+0; v=j+0;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v]).x()  );
						glVertex3fv( &(vertices[s][u][v]).x() );

						u=i+1; v=j+0;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v]).x()  );
						glVertex3fv( &(vertices[s][u][v]).x() );

						u=i+1; v=j+1;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v]).x()  );
						glVertex3fv( &(vertices[s][u][v]).x() );

						u=i+0; v=j+1;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v]).x()  );
						glVertex3fv( &(vertices[s][u][v]).x() );
					}
					else
					{
						float t = 0.0f;
						float tc = 0.0f;
						//if( i==0 || i == (dim1-2) || j==0 || j == (dim2-2) )
						{
							t = 1.0f;
						}
						//else++
						{
							t = 1.0f + faceMorphPositions[faceIdx];

							t = std::min(10.0f, t);
							t = std::max(0.0f, t);
							
							tc = t;
							//float t = 1.2f;
							//if( s == 0 && i == dim1/2 && j == dim2/2 ) t = 2.0f;
						}



						/// Head

						u=i+0; v=j+0;
						extBL = vertices[s][u][v] + normals[s][u][v] * t;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v] * tc).x()  );
						glVertex3fv( &(extBL.x()) );
						
						u=i+1; v=j+0;
						extBR = vertices[s][u][v]  + normals[s][u][v] * t;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v] * tc).x()  );
						glVertex3fv( &(extBR.x()) );
						
						u=i+1; v=j+1;
						extTR = vertices[s][u][v]  + normals[s][u][v] * t;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v] * tc).x()  );
						glVertex3fv( &(extTR.x()) );
						
						u=i+0; v=j+1;
						extTL = vertices[s][u][v]  + normals[s][u][v] * t;
						glNormal3fv( &(normals[s][u][v]).x() );
						glColor3fv( &(colors[s][u][v] * tc).x()  );
						glVertex3fv( &(extTL.x()) );
						
						/////1
						if(1){
							u=i+0; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extTL.x() );

							u=i+1; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extTR.x() );

							u=i+1; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );

							u=i+0; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );
						}

						//////2
						if(1){
							u=i+0; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );

							u=i+1; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );

							u=i+1; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extBR.x() );

							u=i+0; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extBL.x() );
						}
						//////3
						if(1){
							u=i+0; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extBR.x() );

							u=i+1; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );

							u=i+1; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() ); 

							u=i+0; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extTR.x() );
						}  
						//////4
						if(1){
							u=i+0; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );

							u=i+1; v=j+0;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extBR.x() );

							u=i+1; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &extTR.x() );

							u=i+0; v=j+1;
							glNormal3fv( &(normals[s][u][v]).x() );
							glColor3fv( &(colors[s][u][v] * tc).x()  );
							glVertex3fv( &(vertices[s][u][v] * t).x() );     
						}

						faceIdx++;
					} // turn on/off sides
				} // for j
				glEnd();
			} // for i
		} // for s
	}

	int TesselCube::getFaceCount()
	{
		return dim1 * dim2 * 6;
	}

	void TesselCube::setMorphPos( int faceIdx, float t )
	{
		faceMorphPositions[faceIdx] = t;
	}

	Vec3f TesselCube::getVertexColor( int idx )
	{
		int s = 0;
		int ci = 0;
		int cj = 0;
		for(int i=0; i < idx; i++)
		{
			ci++;
			if( ci > dim1-1 )
			{
				ci=0;
				cj++;
			}

			if( cj > dim2-1 )
			{
				cj = 0;
				s++;
			}

			
		}

		return colors[s][ci][cj];
	}

	

